﻿using System;
using System.Runtime.Serialization;
using Flatland.GeneticProgramming;
using Flatland.GeneticProgramming.CoreTypes;
using Flatland.Utilities;
using Microsoft.Xna.Framework;

namespace Flatland.GeneBank {

    /// <summary>
    /// Skin GenoType controls the color and skin texture of a Flatlander.
    /// </summary>
    [Serializable]
    public class Skin : GenoType, IExpression<Color> {
        private Color _color;
        private bool _set;

        protected override void Act(ref string msg) {
            if (!_set) {
                Colors = Utils.SystemColors();
                _color = (Color) Execute();
                _color.A = 255;
                Agent.UpdateShape(Agent.Vertices(), _color, Agent.Size);
                _set = true;
            }
        }

        public override double Fitness() {
            _color = (Color) Execute();
            return Utils.Random.Next(GP.DEFAULT_FITNESS_GOAL);
        }

        [Primitive]
        public Color R = new Color { R = 1 };

        [Primitive]
        public Color G = new Color { G = 1 };

        [Primitive]
        public Color B = new Color { B = 1 };

        [Primitive]
        public Color Clear;

        [Primitive]
        public Color[] Colors = new Color[100];


        [Primitive]
        public Color Add(Color a, Color b) { return new Color((a.R + b.R) % 256, (a.G + b.G) % 256, (a.B + b.B) % 256); }

        [Primitive]
        public Color Sub(Color a, Color b) { return new Color(Math.Abs(a.R - b.R), Math.Abs(a.G - b.G), Math.Abs(a.B - b.B)); }

        [Primitive]
        public Color Mod(Color a, Color b) { return new Color(a.R % (1 + b.R), a.G % (1 + b.G), a.B % (1 + b.B)); }

        [Primitive]
        public Color Exclude(Color a, Color b) {
            return a;
        }

        [Primitive]
        public Color Cross(Color a, Color b) { return new Color(Math.Abs(a.R - 1), a.G, (a.B + 1) % 256); }

        [Primitive]
        public Color Darken(Color a) {
            return new Color(Math.Abs(a.R - 1), Math.Abs(a.G - 1), Math.Abs(a.B - 1));
        }

        [Primitive]
        public Color Lighten(Color a) {
            return new Color((a.R + 1) % 256, (a.G + 1) % 256, (a.B + 1) % 256);
        }

        public Skin(SerializationInfo info, StreamingContext context) {
        }

        public Skin() { }


        public override object Clone(){
            return new Skin();
        }
    }
}
